package com.rizzo.web.validator;

import javax.el.ValueExpression;
import javax.faces.application.FacesMessage;
import javax.faces.component.StateHolder;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;
import java.text.MessageFormat;
import java.util.ResourceBundle;
import java.util.regex.Pattern;

/**
 * Checks if the component value matches the regular expression pattern.
 *
 * @author Michael Seghers
 */
public class RegExpValidator implements Validator, StateHolder {

    /**
     * Field pattern
     */
    private String pattern;

    /**
     * Field detailMessage
     */
    private String detailMessage;

    /**
     * Field summaryMessage
     */
    private String summaryMessage;


    /**
     * {@inheritDoc}
     */
    public void validate(FacesContext facesContext, UIComponent uiComponent, Object value) throws ValidatorException {
        if (!Pattern.matches(pattern, (String) value)) {
            ResourceBundle messageBundle = ResourceBundle.getBundle(facesContext.getApplication().getMessageBundle(),
                    facesContext.getViewRoot().getLocale());
            Object label = uiComponent.getAttributes().get("label");
            if (label == null || (label instanceof String && ((String) label).length() == 0)) {
                ValueExpression valueExpression = uiComponent.getValueExpression("label");
                if (valueExpression != null) {
                    label = valueExpression.getValue(facesContext.getELContext());
                }
            }

            if (label == null) {
                label = uiComponent.getId();
            }

            String summary = MessageFormat.format(summaryMessage == null ? messageBundle
                    .getString("validation.regExpValidator.summary") : summaryMessage, label, (String) value);
            String detail = MessageFormat.format(detailMessage == null ? messageBundle
                    .getString("validation.regExpValidator.detail") : detailMessage, label, (String) value);

            throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, summary, detail));
        }
    }

    /**
     * Setter for property 'pattern'.
     *
     * @param pattern Value to set for property 'pattern'.
     */
    public void setPattern(String pattern) {
        this.pattern = pattern;
    }

    /**
     * Method setDetailMessage sets the detailMessage of this RegExpValidator object.
     *
     * @param detailMessage the detailMessage of this RegExpValidator object.
     */
    public void setDetailMessage(String detailMessage) {
        this.detailMessage = detailMessage;
    }

    /**
     * Method setSummaryMessage sets the summaryMessage of this RegExpValidator object.
     *
     * @param summaryMessage the summaryMessage of this RegExpValidator object.
     */
    public void setSummaryMessage(String summaryMessage) {
        this.summaryMessage = summaryMessage;
    }

    /**
     * {@inheritDoc}
     */
    public boolean isTransient() {
        return false;
    }

    /**
     * {@inheritDoc}
     */
    public void restoreState(FacesContext facesContext, Object state) {
        Object[] values = (Object[]) state;
        pattern = (String) values[0];
        detailMessage = (String) values[1];
        summaryMessage = (String) values[2];
    }

    /**
     * {@inheritDoc}
     */
    public Object saveState(FacesContext facesContext) {
        Object[] state = new Object[3];
        state[0] = pattern;
        state[1] = detailMessage;
        state[2] = summaryMessage;
        return state;
    }

    /**
     * {@inheritDoc}
     */
    public void setTransient(boolean arg0) {
	}

}
